#ifndef __DebugOutputLog_H__
#define __DebugOutputLog_H__
#include <stdio.h>
#include <stdarg.h>
#ifdef WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#else
#include <sys/time.h>
#endif
#include <time.h>
#include <stdio.h>
#include "loggerdefine.h"
#if defined(_MSC_VER) && _MSC_VER < 1600
#include "win32/stdint.h"
#elif defined(_MSC_PLATFORM_TOOLSET) && _MSC_PLATFORM_TOOLSET < 100
#include "win32/stdint.h"
#else
#include <stdint.h>
#endif

class DebugOut_
{
public:
	static void DebugOut(const char* str)
	{
#if defined(DEBUG) || defined(_DEBUG)
  #ifdef WIN32
		OutputDebugStringA(str);
  #else
        printf("%s", str);
  #endif
#endif//_DEBUG
	}

	static void DebugOutF(const char* format,...)
	{
#if defined(DEBUG) || defined(_DEBUG)
		va_list varg;
		va_start(varg, format);
		int len = _vscprintf(format, varg);
		char* fmtstr = new char[len + 1];
		fmtstr[len] = 0;
		vsnprintf(fmtstr, len, format, varg);
		va_end(varg);
		
  #ifdef WIN32
		OutputDebugStringA(fmtstr);
  #else
        printf("%s", fmtstr);
  #endif
		delete[] fmtstr;
#endif//_DEBUG
	}

    static void OutputStringF(const char* format,...)
    {
        va_list varg;
        va_start(varg, format);
		int len = _vscprintf(format, varg);
		char* fmtstr = new char[len+1];
		fmtstr[len] = 0;
		vsnprintf(fmtstr, len, format, varg);
        va_end(varg);

#if defined(WIN32)
        OutputDebugStringA(fmtstr);
#endif
        printf("%s", fmtstr);
		delete[] fmtstr;
    }

    static void OutputlnStringF(const char* format,...)
    {
        va_list varg;
        va_start(varg, format);
		int len = _vscprintf(format, varg);
		char* fmtstr = new char[len + 1];
		fmtstr[len] = 0;
		vsnprintf(fmtstr, len, format, varg);
        va_end(varg);

#if defined(WIN32)
        OutputDebugStringA(fmtstr);
        OutputDebugStringA("\n");
#endif
        printf("%s\n", fmtstr);
		delete[] fmtstr;
    }

    static void PrintLog(const char* format, ...)
    {
        //string time 
        char sztime[32] = "";

#ifdef WIN32
        SYSTEMTIME now;
        GetSystemTime(&now);
        sprintf(sztime, "%04d-%02d-%02d %02d:%02d:%02d.%03d", 
            now.wYear, now.wMonth, now.wDay, now.wHour, now.wMinute, now.wSecond, now.wMilliseconds);
#else
        timeval now;
	gettimeofday(&now, 0);

        struct tm         *p;  
        p = localtime(&now.tv_sec);  
        sprintf(sztime,"%04d-%02d-%02d %02d:%02d:%02d.%03d", 
            1900+p->tm_year, 1+p->tm_mon, p->tm_mday, p->tm_hour, p->tm_min, p->tm_sec, (int)now.tv_usec/1000);  
#endif

        va_list varg;
        va_start(varg, format);
		int len = _vscprintf(format, varg);
		char* fmtstr = new char[len + 1];
		fmtstr[len] = 0;
		vsnprintf(fmtstr, len, format, varg);
        va_end(varg);

        OutputStringF("[%s]\t %s", sztime, fmtstr);
		delete[] fmtstr;

        return ;
    }

    static void PrintlnLog(const char* format, ...)
    {
        //string time 
        char sztime[32] = "";

#ifdef WIN32
        SYSTEMTIME now;
        GetSystemTime(&now);
        sprintf(sztime, "%04d-%02d-%02d %02d:%02d:%02d.%03d", 
            now.wYear, now.wMonth, now.wDay, now.wHour, now.wMinute, now.wSecond, now.wMilliseconds);
#else
        timeval now;
	gettimeofday(&now, 0);

        struct tm         *p;  
        p = localtime(&now.tv_sec);  
        sprintf(sztime,"%04d-%02d-%02d %02d:%02d:%02d.%03d", 
            1900+p->tm_year, 1+p->tm_mon, p->tm_mday, p->tm_hour, p->tm_min, p->tm_sec, (int)now.tv_usec/1000);  
#endif

        va_list varg;
        va_start(varg, format);
		int len = _vscprintf(format, varg);
		char* fmtstr = new char[len + 1];
		fmtstr[len] = 0;
		vsnprintf(fmtstr, len, format, varg);
        va_end(varg);

        OutputlnStringF("[%s]\t %s", sztime, fmtstr);
		delete[] fmtstr;

        return ;
    }
};
#define DebugOut        DebugOut_::DebugOut
#define DebugOutF       DebugOut_::DebugOutF
#define OutputStringF   DebugOut_::OutputStringF
#define PRINTLOG        DebugOut_::PrintLog
#define PRINTLNLOG      DebugOut_::PrintlnLog
#define LOG_DV          DebugOut_::PrintlnLog

#ifndef RESULT
#define RESULT(x) { \
    HRESULT hr = x; \
    if( FAILED(hr) ) { \
        DebugOutF("return err:0x%x at %s, file: %s, line:%d\n", hr, _T(#x), __FILE__, (DWORD)__LINE__); \
    } \
}
#endif

#ifndef RESULT_RETURN
#define RESULT_RETURN(x) { \
HRESULT hr = x; \
    if( FAILED(hr) ) { \
        DebugOutF("return err:0x%x at %s, file: %s, line:%d\n", hr, _T(#x), __FILE__, (DWORD)__LINE__); \
        return hr; \
    } \
}
#endif

#ifndef RESULT_THROW
#define RESULT_THROW(x) { \
    HRESULT hr = x; \
    if( FAILED(hr)) { \
        DebugOutF("return err:0x%x at %s, file: %s, line:%d\n", hr, _T(#x), __FILE__, (DWORD)__LINE__); \
        throw hr; \
    } \
}
#endif


#ifndef CHECK_BRESULT
#define CHECK_BRESULT(x) { \
    bool hr = x; \
    if (!hr) { \
        DebugOutF("return err:%d, file: %s, line:%d\n", hr, __FILE__, (DWORD)__LINE__); \
        return false; \
    } \
}
#endif

#endif //__DebugOutputLog_H__

